/**
 * @file snakegamestate.cpp
 * @brief Snake游戏状态管理类实现文件
 *
 * 实现Snake游戏状态管理的所有功能，包括：
 * - 游戏状态的存储和更新
 * - JSON数据的解析和处理
 * - 游戏对象的管理和查询
 * - 状态变化的事件通知
 * - 游戏逻辑的辅助功能
 */

#include "../include/snakegamestate.h"
#include <QDebug>               // 调试输出
#include <QJsonDocument>        // JSON文档处理
#include <QRandomGenerator>     // 随机数生成
#include <QCryptographicHash>   // 哈希计算

/**
 * @brief SnakeGameState构造函数
 * @param parent 父对象指针
 *
 * 初始化游戏状态管理器：
 * 1. 设置默认状态值
 * 2. 初始化游戏板参数
 * 3. 清空游戏对象列表
 */
SnakeGameState::SnakeGameState(QObject *parent)
    : QObject(parent)
    , m_gameStatus(SnakeGameState::GameStatus::Waiting)
    , m_boardWidth(40)
    , m_boardHeight(30)
    , m_tickCount(0)
    , m_gameSpeed(100)
{
    qDebug() << "SnakeGameState initialized";
}

/**
 * @brief SnakeGameState析构函数
 */
SnakeGameState::~SnakeGameState()
{
    qDebug() << "SnakeGameState destroyed";
}

/**
 * @brief 从JSON更新游戏状态
 * @param stateJson 服务器发送的游戏状态JSON
 */
void SnakeGameState::updateFromJson(const QJsonObject &stateJson)
{
    qDebug() << "Updating game state from JSON";
    
    // === 更新基本游戏信息 ===
    if (stateJson.contains("room_id")) {
        QString newRoomId = stateJson["room_id"].toString();
        if (m_roomId != newRoomId) {
            m_roomId = newRoomId;
            qDebug() << "Room ID updated to:" << m_roomId;
        }
    }
    
    // === 处理数字类型的status（服务器返回格式） ===
    if (stateJson.contains("status")) {
        int statusInt = stateJson["status"].toInt();
        SnakeGameState::GameStatus newStatus = SnakeGameState::GameStatus::Waiting;

        switch (statusInt) {
            case 0: newStatus = SnakeGameState::GameStatus::Waiting; break;
            case 1: newStatus = SnakeGameState::GameStatus::Playing; break;
            case 2: newStatus = SnakeGameState::GameStatus::Paused; break;
            case 3: newStatus = SnakeGameState::GameStatus::Finished; break;
            default: newStatus = SnakeGameState::GameStatus::Error; break;
        }
        
        setGameStatus(newStatus);
        qDebug() << "Game status updated from server:" << statusInt << "mapped to:" << static_cast<int>(newStatus);
    }
    
    // === 兼容字符串类型的game_status ===
    if (stateJson.contains("game_status")) {
        QString statusStr = stateJson["game_status"].toString();
        SnakeGameState::GameStatus newStatus = SnakeGameState::GameStatus::Waiting;

        if (statusStr == "waiting") newStatus = SnakeGameState::GameStatus::Waiting;
        else if (statusStr == "starting") newStatus = SnakeGameState::GameStatus::Starting;
        else if (statusStr == "playing") newStatus = SnakeGameState::GameStatus::Playing;
        else if (statusStr == "paused") newStatus = SnakeGameState::GameStatus::Paused;
        else if (statusStr == "finished") newStatus = SnakeGameState::GameStatus::Finished;
        else newStatus = SnakeGameState::GameStatus::Error;
        
        setGameStatus(newStatus);
        qDebug() << "Game status updated from string:" << statusStr;
    }
    
    // === 更新游戏板信息 - 支持服务器data.map结构 ===
    if (stateJson.contains("data")) {
        QJsonObject dataObj = stateJson["data"].toObject();
        
        // 从data.map获取地图信息
        if (dataObj.contains("map")) {
            QJsonObject mapObj = dataObj["map"].toObject();
            int newWidth = mapObj["width"].toInt(40);  // 默认40
            int newHeight = mapObj["height"].toInt(30); // 默认30
            
            if (m_boardWidth != newWidth || m_boardHeight != newHeight) {
                m_boardWidth = newWidth;
                m_boardHeight = newHeight;
                emit boardSizeChanged(m_boardWidth, m_boardHeight);
                qDebug() << "Board size updated from data.map:" << m_boardWidth << "x" << m_boardHeight;
            }
        }
    }
    
    // === 兼容旧格式的游戏板信息 ===
    if (stateJson.contains("board_width")) {
        int newWidth = stateJson["board_width"].toInt();
        int newHeight = stateJson["board_height"].toInt();
        
        if (m_boardWidth != newWidth || m_boardHeight != newHeight) {
            m_boardWidth = newWidth;
            m_boardHeight = newHeight;
            emit boardSizeChanged(m_boardWidth, m_boardHeight);
            qDebug() << "Board size updated from legacy format:" << m_boardWidth << "x" << m_boardHeight;
        }
    }
    
    if (stateJson.contains("tick_count")) {
        m_tickCount = stateJson["tick_count"].toInt();
    }
    
    if (stateJson.contains("game_speed_ms")) {
        m_gameSpeed = stateJson["game_speed_ms"].toInt();
    }
    
    // === 更新蛇数据 - 支持服务器data结构 ===
    if (stateJson.contains("data")) {
        QJsonObject dataObj = stateJson["data"].toObject();
        
        if (dataObj.contains("snakes")) {
            QJsonArray snakesArray = dataObj["snakes"].toArray();
            parseSnakes(snakesArray);
        }
        
        if (dataObj.contains("foods")) {
            QJsonArray foodsArray = dataObj["foods"].toArray();
            parseFoods(foodsArray);
        }
        
        // 更新tick_count
        if (dataObj.contains("tick_count")) {
            m_tickCount = dataObj["tick_count"].toInt();
        }
    }
    
    // === 兼容直接格式的蛇数据 ===
    if (stateJson.contains("snakes")) {
        QJsonArray snakesArray = stateJson["snakes"].toArray();
        parseSnakes(snakesArray);
    }
    
    // === 兼容直接格式的食物数据 ===
    if (stateJson.contains("foods")) {
        QJsonArray foodsArray = stateJson["foods"].toArray();
        parseFoods(foodsArray);
    }
    
    // === 发送状态更新信号 ===
    emit stateUpdated();
}

/**
 * @brief 重置游戏状态
 */
void SnakeGameState::reset()
{
    qDebug() << "Resetting game state";
    
    // === 重置基本状态 ===
    setGameStatus(SnakeGameState::GameStatus::Waiting);
    m_tickCount = 0;
    
    // === 清空游戏对象 ===
    m_snakes.clear();
    m_foods.clear();
    m_playerSnakeMap.clear();
    
    // === 发送重置信号 ===
    emit stateUpdated();
}

/**
 * @brief 清空所有数据
 */
void SnakeGameState::clear()
{
    qDebug() << "Clearing all game state data";
    
    // === 清空所有数据 ===
    m_roomId.clear();
    m_currentPlayerId.clear();
    setGameStatus(SnakeGameState::GameStatus::Waiting);
    m_boardWidth = 40;
    m_boardHeight = 30;
    m_tickCount = 0;
    m_gameSpeed = 100;
    
    m_snakes.clear();
    m_foods.clear();
    m_playerSnakeMap.clear();
    
    emit stateUpdated();
}

/**
 * @brief 获取指定玩家的蛇数据
 * @param playerId 玩家ID
 * @return 蛇数据指针，如果不存在返回nullptr
 */
const SnakeData* SnakeGameState::getPlayerSnake(const QString& playerId) const
{
    auto it = m_playerSnakeMap.find(playerId);
    if (it != m_playerSnakeMap.end() && it.value() < m_snakes.size()) {
        return &m_snakes[it.value()];
    }
    return nullptr;
}

/**
 * @brief 获取当前玩家的蛇数据
 * @return 当前玩家蛇数据指针，如果不存在返回nullptr
 */
const SnakeData* SnakeGameState::getCurrentPlayerSnake() const
{
    if (m_currentPlayerId.isEmpty()) {
        return nullptr;
    }
    return getPlayerSnake(m_currentPlayerId);
}

/**
 * @brief 获取存活的蛇数量
 * @return 存活蛇数量
 */
int SnakeGameState::getAliveSnakeCount() const
{
    int count = 0;
    for (const SnakeData& snake : m_snakes) {
        if (snake.isAlive) {
            count++;
        }
    }
    return count;
}

/**
 * @brief 获取指定位置的食物
 * @param position 位置
 * @return 食物数据指针，如果不存在返回nullptr
 */
const FoodData* SnakeGameState::getFoodAt(const Position& position) const
{
    for (const FoodData& food : m_foods) {
        if (food.position == position) {
            return &food;
        }
    }
    return nullptr;
}

/**
 * @brief 获取玩家列表
 * @return 玩家ID列表
 */
QStringList SnakeGameState::getPlayerIds() const
{
    QStringList playerIds;
    for (const SnakeData& snake : m_snakes) {
        playerIds.append(snake.playerId);
    }
    return playerIds;
}

/**
 * @brief 检查位置是否在游戏板内
 * @param position 位置
 * @return true表示在游戏板内
 */
bool SnakeGameState::isPositionValid(const Position& position) const
{
    return position.x >= 0 && position.x < m_boardWidth &&
           position.y >= 0 && position.y < m_boardHeight;
}

/**
 * @brief 检查位置是否被蛇占用
 * @param position 位置
 * @param excludePlayerId 排除的玩家ID（可选）
 * @return true表示被占用
 */
bool SnakeGameState::isPositionOccupiedBySnake(const Position& position, const QString& excludePlayerId) const
{
    for (const SnakeData& snake : m_snakes) {
        if (!snake.isAlive || snake.playerId == excludePlayerId) {
            continue;
        }
        
        for (const Position& bodyPos : snake.body) {
            if (bodyPos == position) {
                return true;
            }
        }
    }
    return false;
}

/**
 * @brief 检查位置是否有食物
 * @param position 位置
 * @return true表示有食物
 */
bool SnakeGameState::isPositionHasFood(const Position& position) const
{
    return getFoodAt(position) != nullptr;
}

/**
 * @brief 获取方向向量
 * @param direction 方向
 * @return 方向向量
 */
Position SnakeGameState::getDirectionVector(Direction direction)
{
    switch (direction) {
    case Direction::Up:    return Position(0, -1);
    case Direction::Right: return Position(1, 0);
    case Direction::Down:  return Position(0, 1);
    case Direction::Left:  return Position(-1, 0);
    }
    return Position(0, 0);
}

/**
 * @brief 检查方向是否相反
 * @param dir1 方向1
 * @param dir2 方向2
 * @return true表示相反
 */
bool SnakeGameState::areDirectionsOpposite(Direction dir1, Direction dir2)
{
    return (dir1 == Direction::Up && dir2 == Direction::Down) ||
           (dir1 == Direction::Down && dir2 == Direction::Up) ||
           (dir1 == Direction::Left && dir2 == Direction::Right) ||
           (dir1 == Direction::Right && dir2 == Direction::Left);
}

/**
 * @brief 解析蛇数据
 * @param snakesArray 蛇数据JSON数组
 */
void SnakeGameState::parseSnakes(const QJsonArray& snakesArray)
{
    // === 记录旧的蛇列表 ===
    QSet<QString> oldPlayerIds;
    for (const SnakeData& snake : m_snakes) {
        oldPlayerIds.insert(snake.playerId);
    }
    
    // === 解析新的蛇数据 ===
    QVector<SnakeData> newSnakes;
    QSet<QString> newPlayerIds;
    
    for (const QJsonValue& snakeValue : snakesArray) {
        QJsonObject snakeObj = snakeValue.toObject();
        SnakeData snakeData = parseSnakeData(snakeObj);
        newSnakes.append(snakeData);
        newPlayerIds.insert(snakeData.playerId);
        
        // === 检查分数变化 ===
        const SnakeData* oldSnake = getPlayerSnake(snakeData.playerId);
        if (oldSnake && oldSnake->score != snakeData.score) {
            emit snakeScoreChanged(snakeData.playerId, snakeData.score);
        }
        
        // === 检查死亡状态 ===
        if (oldSnake && oldSnake->isAlive && !snakeData.isAlive) {
            emit snakeDied(snakeData.playerId);
        }
    }
    
    // === 检查新增的蛇 ===
    for (const QString& playerId : newPlayerIds) {
        if (!oldPlayerIds.contains(playerId)) {
            emit snakeAdded(playerId);
        }
    }
    
    // === 检查移除的蛇 ===
    for (const QString& playerId : oldPlayerIds) {
        if (!newPlayerIds.contains(playerId)) {
            emit snakeRemoved(playerId);
        }
    }
    
    // === 更新蛇数据 ===
    m_snakes = newSnakes;
    updatePlayerSnakeMap();
}

/**
 * @brief 解析食物数据
 * @param foodsArray 食物数据JSON数组
 */
void SnakeGameState::parseFoods(const QJsonArray& foodsArray)
{
    // === 记录旧的食物位置 ===
    QSet<Position> oldFoodPositions;
    for (const FoodData& food : m_foods) {
        oldFoodPositions.insert(food.position);
    }

    // === 解析新的食物数据 ===
    QVector<FoodData> newFoods;
    QSet<Position> newFoodPositions;

    for (const QJsonValue& foodValue : foodsArray) {
        QJsonObject foodObj = foodValue.toObject();
        FoodData foodData = parseFoodData(foodObj);
        newFoods.append(foodData);
        newFoodPositions.insert(foodData.position);
    }

    // === 检查新增的食物 ===
    for (const FoodData& food : newFoods) {
        if (!oldFoodPositions.contains(food.position)) {
            emit foodSpawned(food.position, food.type);
        }
    }

    // === 检查消失的食物（被消费或过期） ===
    for (const FoodData& oldFood : m_foods) {
        if (!newFoodPositions.contains(oldFood.position)) {
            if (oldFood.isExpired()) {
                emit foodExpired(oldFood.position);
            } else {
                // 假设被消费了，实际应该从服务器获取消费者信息
                emit foodConsumed(oldFood.position, QString());
            }
        }
    }

    // === 更新食物数据 ===
    m_foods = newFoods;
}

/**
 * @brief 更新玩家蛇映射
 */
void SnakeGameState::updatePlayerSnakeMap()
{
    m_playerSnakeMap.clear();
    for (int i = 0; i < m_snakes.size(); ++i) {
        m_playerSnakeMap[m_snakes[i].playerId] = i;
    }
}

/**
 * @brief 生成玩家颜色
 * @param playerId 玩家ID
 * @return 玩家颜色
 */
QColor SnakeGameState::generatePlayerColor(const QString& playerId)
{
    // === 使用玩家ID生成一致的颜色 ===
    QCryptographicHash hash(QCryptographicHash::Md5);
    hash.addData(playerId.toUtf8());
    QByteArray hashResult = hash.result();

    // === 从哈希值提取RGB值 ===
    int r = static_cast<unsigned char>(hashResult[0]) % 200 + 55; // 55-254
    int g = static_cast<unsigned char>(hashResult[1]) % 200 + 55;
    int b = static_cast<unsigned char>(hashResult[2]) % 200 + 55;

    return QColor(r, g, b);
}

/**
 * @brief 设置游戏状态
 * @param status 新的游戏状态
 */
void SnakeGameState::setGameStatus(SnakeGameState::GameStatus status)
{
    if (m_gameStatus != status) {
        SnakeGameState::GameStatus oldStatus = m_gameStatus;
        m_gameStatus = status;

        qDebug() << "Game status changed from" << static_cast<int>(oldStatus)
                 << "to" << static_cast<int>(status);
        emit gameStatusChanged(status);
    }
}

/**
 * @brief 解析蛇数据
 * @param snakeObj 蛇数据JSON对象
 * @return 蛇数据结构
 */
SnakeData SnakeGameState::parseSnakeData(const QJsonObject& snakeObj)
{
    SnakeData snake;
    snake.playerId = snakeObj["player_id"].toString();
    snake.playerName = snakeObj["player_name"].toString();
    snake.score = snakeObj["score"].toInt();
    snake.isAlive = snakeObj["alive"].toBool();
    snake.direction = parseDirection(snakeObj["direction"].toInt());
    
    // 处理last_move字段（服务器返回格式）
    if (snakeObj.contains("last_move")) {
        snake.lastMoveTime = snakeObj["last_move"].toVariant().toLongLong();
    } else if (snakeObj.contains("last_move_time")) {
        snake.lastMoveTime = snakeObj["last_move_time"].toVariant().toLongLong();
    }

    // === 解析蛇身体 - 支持服务器返回的position格式 ===
    QJsonArray bodyArray = snakeObj["body"].toArray();
    snake.body.clear();
    for (const QJsonValue& posValue : bodyArray) {
        Position pos;
        if (posValue.isObject()) {
            QJsonObject posObj = posValue.toObject();
            // 服务器返回格式: {"type": "position", "x": 13, "y": 5}
            pos.x = posObj["x"].toInt();
            pos.y = posObj["y"].toInt();
        } else {
            // 兼容其他格式
            pos = parsePosition(posValue.toObject());
        }
        snake.body.append(pos);
    }
    snake.length = snake.body.size();

    // === 处理颜色 ===
    if (snakeObj.contains("color")) {
        QString colorStr = snakeObj["color"].toString();
        snake.color = QColor(colorStr);
    } else {
        // 生成玩家颜色
        snake.color = generatePlayerColor(snake.playerId);
    }

    qDebug() << "Parsed snake:" << snake.playerId << "body size:" << snake.body.size() 
             << "alive:" << snake.isAlive << "direction:" << snakeObj["direction"].toInt();

    return snake;
}

/**
 * @brief 解析食物数据
 * @param foodObj 食物数据JSON对象
 * @return 食物数据结构
 */
FoodData SnakeGameState::parseFoodData(const QJsonObject& foodObj)
{
    FoodData food;
    
    // === 解析位置 - 支持服务器返回的position格式 ===
    if (foodObj.contains("position")) {
        QJsonObject posObj = foodObj["position"].toObject();
        // 服务器返回格式: {"type": "position", "x": 23, "y": 7}
        food.position.x = posObj["x"].toInt();
        food.position.y = posObj["y"].toInt();
    }

    // === 使用统一的食物类型解析函数 ===
    food.type = parseFoodType(foodObj["type"]);

    food.value = foodObj["value"].toInt();
    
    // 处理服务器返回的时间字段
    if (foodObj.contains("spawn_time")) {
        food.spawnTime = foodObj["spawn_time"].toVariant().toLongLong();
    }
    if (foodObj.contains("expire_time")) {
        food.expireTime = foodObj["expire_time"].toVariant().toLongLong();
    }
    food.isSpecial = (food.type != "normal");

    // === 根据类型设置颜色 ===
    if (food.type == "special") {
        food.color = Qt::yellow;
    } else if (food.type == "bonus") {
        food.color = Qt::magenta;
    } else if (food.type == "speed") {
        food.color = Qt::green;
    } else if (food.type == "slow") {
        food.color = Qt::blue;
    } else {
        food.color = Qt::red; // 默认颜色
    }

    qDebug() << "Parsed food at position" << food.position.x << food.position.y 
             << "type:" << food.type << "value:" << food.value;

    return food;
}

/**
 * @brief 将食物类型数字转换为字符串
 * @param typeValue JSON值（可能是数字或字符串）
 * @return 食物类型字符串
 */
QString SnakeGameState::parseFoodType(const QJsonValue& typeValue)
{
    if (typeValue.isString()) {
        return typeValue.toString();
    } else if (typeValue.isDouble()) {
        // 将数字类型转换为字符串类型
        int typeInt = typeValue.toInt();
        switch (typeInt) {
            case 0: return "normal";
            case 1: return "special";
            case 2: return "bonus";
            case 3: return "speed";
            case 4: return "slow";
            default:
                qDebug() << "Unknown food type:" << typeInt << ", defaulting to normal";
                return "normal";
        }
    } else {
        return "normal"; // 默认类型
    }
}

/**
 * @brief 解析方向
 * @param directionInt 方向整数值
 * @return 方向枚举
 */
Direction SnakeGameState::parseDirection(int directionInt)
{
    switch (directionInt) {
    case 0: return Direction::Up;
    case 1: return Direction::Right;
    case 2: return Direction::Down;
    case 3: return Direction::Left;
    default: return Direction::Right;
    }
}

/**
 * @brief 解析位置
 * @param posObj 位置JSON对象
 * @return 位置结构
 */
Position SnakeGameState::parsePosition(const QJsonObject& posObj)
{
    return Position(posObj["x"].toInt(), posObj["y"].toInt());
}

/**
 * @brief 静态生成玩家颜色
 * @param playerId 玩家ID
 * @return 玩家颜色
 */
QColor SnakeGameState::generateStaticPlayerColor(const QString &playerId)
{
    // === 预定义颜色列表 ===
    static const QVector<QColor> colors = {
        QColor(76, 175, 80),   // 绿色
        QColor(244, 67, 54),   // 红色
        QColor(33, 150, 243),  // 蓝色
        QColor(255, 152, 0),   // 橙色
        QColor(156, 39, 176),  // 紫色
        QColor(255, 193, 7),   // 黄色
        QColor(0, 188, 212),   // 青色
        QColor(255, 87, 34)    // 深橙色
    };

    // === 根据玩家ID生成哈希值选择颜色 ===
    uint hash = qHash(playerId);
    return colors[hash % colors.size()];
}
